package cn.ydxiaoshuai.tools.util;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.ydxiaoshuai.tools.conts.ImageBase64Conts;
import cn.ydxiaoshuai.tools.conts.JobConts;
import com.baidu.aip.util.Base64Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

/**
 * @ClassName: MergeImageUtil
 * @description: 图片融合(两张图片合并为一张图片)
 * @author: 小帅丶
 * @create: 2019-04-08
 **/
@Slf4j
@Component
public class MergeImageUtil {
    @Autowired
    private RedisUtil redisUtil;
    /**
     * 缩放比例系数
     */
    private static double SCALING = 0.56;
    /**
     * 缩放比例系数
     */
    private static double SCALING_LITE = 0.75;
    /**
     * 符合base64的宽
     */
    private static int MAX_WIDTH_LITE = 350;
    /**
     * 最大高
     */
    private static int MAX_HEIGHT_LITE = 466;
    /**
     * 符合base64的宽
     */
    private static int MAX_WIDTH = 560;
    /**
     * 最大高
     */
    private static int MAX_HEIGHT = 1000;

    /**
     * @Author 小帅丶
     * @Description 合成分享海报
     * @Date  2020/10/13 18:39
     * @param baldImg 合成后的图片
     * @param jobNum 编码
     * @return java.lang.String
     **/
    public String mergePendant(String nickName,String jobNum,byte[] baldImg) throws Exception{
        long startTime = System.currentTimeMillis();
        //填充后的图片
        BufferedImage image;
        //#背景图读取
        byte[] posterByte = FileUtil.readBytes("/usr/local/poster/poster.png");
        //byte[] posterByte = Base64Util.decode(ImageBase64Conts.POSTER);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(posterByte);
        BufferedImage src = ImageIO.read(byteArrayInputStream);
        //BufferedImage src = imgUrlConvertBufferedImage("https://xai-1251091977.cos.ap-chengdu.myqcloud.com/src.jpg");
        //头像读取-转换成圆形透明
        //BufferedImage avatar = transferImgForRoundImgage(avatarUrl);
        //#合成图读取
        ByteArrayInputStream byteBaldImg = new ByteArrayInputStream(baldImg);
        //BufferedImage merge = ImageIO.read(byteBaldImg);
        BufferedImage merge = zoomImage(baldImg,MAX_WIDTH_LITE,MAX_HEIGHT_LITE,SCALING_LITE);
        //#二维码读取
        byte[] qrCodeByte = FileUtil.readBytes("/usr/local/poster/qrcode.jpg");
        ByteArrayInputStream byteQrCode = new ByteArrayInputStream(qrCodeByte);
        BufferedImage qrCode = ImageIO.read(byteQrCode);
        //图片填充
        //String avatars[] = redisUtil.get(JobConts.AVATAR_KEY).toString().split(",");
        String merges[] = redisUtil.get(JobConts.MERGE_KEY).toString().split(",");
        String qrcodes[] = redisUtil.get(JobConts.QRCODE_KEY).toString().split(",");
        String nickNames[] = redisUtil.get(JobConts.NICKNAME_KEY).toString().split(",");
        String jobNums[] = redisUtil.get(JobConts.JOBNUM_KEY).toString().split(",");
        //image = mergePendant(src, avatar, Integer.parseInt(avatars[0]), Integer.parseInt(avatars[1]), 1);
        image = mergePendant(src, merge, Integer.parseInt(merges[0]), Integer.parseInt(merges[1]), 1);
        image = mergePendant(image, qrCode, Integer.parseInt(qrcodes[0]), Integer.parseInt(qrcodes[1]), 1);
        //转成2d画板 对图片进行文本内容填充
        Graphics2D g = (Graphics2D) image.getGraphics();
        //#微信昵称
        Font fontNickName = new Font("微软雅黑", Font.PLAIN, 32);
        g.setStroke(new BasicStroke(2.0f));
        g.setColor(Color.BLACK);
        g.setFont(fontNickName);
        String nickNameDe = URLDecoder.decode(nickName, "UTF-8");
        if(nickNameDe.length()>8){
            nickNameDe = nickNameDe.substring(0,7)+"...";
        }
        g.drawString(nickNameDe,Integer.parseInt(nickNames[0]),Integer.parseInt(nickNames[1]));
        //#工号
        Font fontJobNum = new Font("微软雅黑", Font.PLAIN, 32);
        g.setStroke(new BasicStroke(2.0f));
        g.setColor(Color.BLACK);
        g.setFont(fontJobNum);
        g.drawString("工号："+jobNum,Integer.parseInt(jobNums[0]),Integer.parseInt(jobNums[1]));
        //#评分
        Font fontLevel = new Font("微软雅黑", Font.PLAIN, 64);
        g.setStroke(new BasicStroke(2.5f));
        g.setColor(new Color(7,110,232));
        g.setFont(fontLevel);
        String[] strings = randomLevel();
        g.drawString(strings[0],432,2017);
        g.drawString(strings[1],623,2017);
        g.drawString(strings[2],813,2017);
        g.drawString(strings[3],1003,2017);
        //#星星
        String star = randomStar();
        Font fontStar = new Font("微软雅黑", Font.PLAIN, 64);
        g.setStroke(new BasicStroke(2.5f));
        g.setColor(new Color(7,110,232));
        g.setFont(fontStar);
        g.drawString(star,610,2130);
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", outputStream);
        String base64Img = Base64Util.encode(outputStream.toByteArray());
        long endTime = System.currentTimeMillis();
        log.info("海报合成耗时:{}",(endTime-startTime));
        return base64Img;
    }
    /**
     * @Author 小帅丶
     * @Description 秃头、码龄、社畜、颜值随机指数
     * @Date  2020/10/19 17:50
     * @return java.lang.String[]
     **/
    private String[] randomLevel() {
        int max=10;
        int min=1;
        Random random = new Random();
        int s = random.nextInt(max)%(max-min+1) + min;
        HashMap<Integer,String[]> index = new HashMap<>();
        //秃头、码龄、社畜、颜值
        index.put(1, new String[]{"9.7","9.6","9.8","9.9"});
        index.put(2, new String[]{"9.7","9.5","9.7","9.9"});
        index.put(3, new String[]{"9.6","9.8","9.8","9.9"});
        index.put(4, new String[]{"9.6","9.7","9.7","9.9"});
        index.put(5, new String[]{"9.8","9.6","9.8","9.9"});
        index.put(6, new String[]{"9.8","9.5","9.9","9.9"});
        index.put(7, new String[]{"9.9","9.6","9.8","9.9"});
        index.put(8, new String[]{"9.9","9.7","9.9","9.9"});
        index.put(9, new String[]{"9.5","9.8","9.8","9.9"});
        index.put(10, new String[]{"9.5","9.9","9.9","9.9"});
        String[] strings = index.get(s);
        return strings;
    }

    /**
     * @Author 小帅丶
     * @Description 随机等级
     * @Date  2020/10/19 17:50
     * @return java.lang.String
     **/
    private String randomStar() {
        int max=5;
        int min=1;
        Random random = new Random();
        String star = "★ ★ ★ ★ ";
        int s = random.nextInt(max)%(max-min+1) + min;
        if(s==1){
            star = "★ ★ ";
        }
        if(s==2){
            star = "★ ★ ★ ";
        }
        if(s==3){
            star = "★ ★ ★ ";
        }
        if(s==4){
            star = "★ ★ ★ ★ ";
        }
        if(s==5){
            star = "★ ★ ★ ★ ★ ";
        }
        return star;
    }

    /**
     * 两张图片合并为一张图片
     * @param srcImage 底图
     * @param pendantImage 挂件图
     * @param x 距离右下角的X偏移量
     * @param y 距离右下角的Y偏移量
     * @param alpha  透明度, 选择值从0.0~1.0: 完全透明~完全不透明
     * @return BufferedImage
     * @throws Exception
     */
    public  BufferedImage mergePendant(BufferedImage srcImage, BufferedImage pendantImage, int x, int y, float alpha)throws Exception {
        //创建Graphics2D对象 用在挂件图像对象上绘图
        Graphics2D g2d = srcImage.createGraphics();
        //获取挂件图像的宽高
        int pendantImageWidth = pendantImage.getWidth();
        int pendantImageHeight = pendantImage.getHeight();
        //实现混合和透明效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha));
        //绘制图像
        g2d.drawImage(pendantImage,x,y,pendantImageWidth,pendantImageHeight,null);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        return  srcImage;
    }

    /**
     * @Author 小帅丶
     * @Description 根据BufferedImage处理图片并返回byte[]
     * @Date  2020/9/29 10:55
     * @param bufferedImage
     * @return byte[]
     **/
    public static byte[] zoomImageByte(BufferedImage bufferedImage) throws Exception {
        ByteArrayOutputStream outputStreamZoom = new ByteArrayOutputStream();
        ByteArrayOutputStream outputStreamSource = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", outputStreamSource);
        BufferedImage bufferedImageZoom = zoomImage(outputStreamSource.toByteArray());
        //写入缩减后的图片
        ImageIO.write(bufferedImageZoom, "jpg", outputStreamZoom);
        return outputStreamZoom.toByteArray();
    }


    /**
     * @Author 小帅丶
     * @Description 根据byte[]处理图片并返回byte[]
     * @Date  2020/9/29 10:55
     * @param src
     * @return byte[]
     **/
    public byte[] zoomImageByte(byte[] src) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        BufferedImage bufferedImage = zoomImage(src);
        //写入缩减后的图片
        ImageIO.write(bufferedImage, "jpg", outputStream);
        return outputStream.toByteArray();
    }

    /**
     * 图片缩放
     *
     * @param src 为源文件byte
     */
    public BufferedImage zoomImageNostatic(byte[] src,int MAX_WIDTH,int MAX_HEIGHT) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(src);
        double wr = 0, hr = 0;
        BufferedImage bufferedImage = null;
        //读取图片
        BufferedImage bufImg = ImageIO.read(in);
        int height = bufImg.getHeight();
        int width = bufImg.getWidth();
        int cHeight = height;
        int cWidth = width;
        double Scaling = width / height;
        if (Scaling < SCALING) {
            if (height > MAX_HEIGHT) {
                cHeight = MAX_HEIGHT;
                cWidth = (width * MAX_HEIGHT) / height;
            }
            //以宽为缩放比例
        } else {
            if (width > MAX_WIDTH) {
                cWidth = MAX_WIDTH;
                cHeight = (height * MAX_WIDTH) / width;
            }
        }
        //获取缩放后的宽高
        log.info("宽{},高{}", cWidth, cHeight);
        //设置缩放目标图片模板
        Image Itemp = bufImg.getScaledInstance(width, cHeight, BufferedImage.SCALE_SMOOTH);
        //获取缩放比例
        wr = cWidth * 1.0 / width;
        hr = cHeight * 1.0 / height;
        log.info("宽比例{},高比例{}", wr, hr);
        AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null);
        Itemp = ato.filter(bufImg, null);
        try {
            //写入缩减后的图片
            ImageIO.write((BufferedImage) Itemp, "jpg", outputStream);
            ByteArrayInputStream inNew = new ByteArrayInputStream(outputStream.toByteArray());
            bufferedImage = ImageIO.read(inNew);
        } catch (Exception ex) {
            log.info("缩放图片异常{}", ex.getMessage());
        } finally {
            if (null != outputStream) {
                outputStream.close();
            }
            if (null != in) {
                in.close();
            }
        }
        return bufferedImage;
    }
    /**
     * 图片缩放
     *
     * @param src 为源文件byte
     */
    public static BufferedImage zoomImage(byte[] src,int MAX_WIDTH,int MAX_HEIGHT,double SCALING) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(src);
        double wr = 0, hr = 0;
        BufferedImage bufferedImage = null;
        //读取图片
        BufferedImage bufImg = ImageIO.read(in);
        int height = bufImg.getHeight();
        int width = bufImg.getWidth();
        int cHeight = height;
        int cWidth = width;
        double Scaling = width / height;
        if (Scaling < SCALING) {
            if (height > MAX_HEIGHT) {
                cHeight = MAX_HEIGHT;
                cWidth = (width * MAX_HEIGHT) / height;
            }
            //以宽为缩放比例
        } else {
            if (width > MAX_WIDTH) {
                cWidth = MAX_WIDTH;
                cHeight = (height * MAX_WIDTH) / width;
            }
        }
        //获取缩放后的宽高
        log.info("宽{},高{}", cWidth, cHeight);
        //设置缩放目标图片模板
        Image Itemp = bufImg.getScaledInstance(width, cHeight, BufferedImage.SCALE_SMOOTH);
        //获取缩放比例
        wr = cWidth * 1.0 / width;
        hr = cHeight * 1.0 / height;
        log.info("宽比例{},高比例{}", wr, hr);
        AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null);
        Itemp = ato.filter(bufImg, null);
        try {
            //写入缩减后的图片
            ImageIO.write((BufferedImage) Itemp, "jpg", outputStream);
            ByteArrayInputStream inNew = new ByteArrayInputStream(outputStream.toByteArray());
            bufferedImage = ImageIO.read(inNew);
        } catch (Exception ex) {
            log.info("缩放图片异常{}", ex.getMessage());
        } finally {
            if (null != outputStream) {
                outputStream.close();
            }
            if (null != in) {
                in.close();
            }
        }
        return bufferedImage;
    }

    /**
     * 图片缩放 仅适用于微信内容图片安全检测使用
     *
     * @param src 为源文件byte
     */
    public static BufferedImage zoomImage(byte[] src) throws Exception {
       return zoomImage(src, MAX_WIDTH, MAX_HEIGHT,SCALING);
    }

    /**
     * @Author 小帅丶
     * @Description 根据图片公网地址转BufferedImage
     * @Date  2020/9/29 10:52
     * @param url 图片公网地址
     * @return java.awt.image.BufferedImage
     **/
    public static BufferedImage imgUrlConvertBufferedImage(String url) throws Exception {
        URL urls = new URL(url);
        Image image = Toolkit.getDefaultToolkit().getImage(urls);
        BufferedImage bufferedImage = toBufferedImage(image);
        return bufferedImage;
    }

    /**
     * @Author 小帅丶
     * @Description Image转BufferedImage
     * @Date  2020/9/29 10:47
     * @param image 通过url获取的image对象
     * @return java.awt.image.BufferedImage
     **/
    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }
        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment
                .getLocalGraphicsEnvironment();
        try {
            int transparency = Transparency.OPAQUE;
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(image.getWidth(null),
                    image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }
        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            bimage = new BufferedImage(image.getWidth(null),
                    image.getHeight(null), type);
        }
        // Copy image to buffered image
        Graphics g = bimage.createGraphics();
        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return bimage;
    }

    /**
     * 将图片处理为圆形图片
     * 传入的图片必须是正方形的才会生成圆形 如果是长方形的比例则会变成椭圆的
     *
     * @param url
     * @return
     */
    public BufferedImage transferImgForRoundImgage(String url) {
        BufferedImage resultImg = null;
        try {
            if (null==url) {
                return null;
            }
            BufferedImage buffImg1 = ImageIO.read(new URL(url));
            resultImg = new BufferedImage(buffImg1.getWidth(), buffImg1.getHeight(), BufferedImage.TYPE_INT_RGB);
            Graphics2D g = resultImg.createGraphics();
            Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, buffImg1.getWidth(), buffImg1.getHeight());
            // 使用 setRenderingHint 设置抗锯齿
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            resultImg = g.getDeviceConfiguration().createCompatibleImage(buffImg1.getWidth(), buffImg1.getHeight(),
                    Transparency.TRANSLUCENT);
            g = resultImg.createGraphics();
            // 使用 setRenderingHint 设置抗锯齿
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setClip(shape);
            g.drawImage(buffImg1, 0, 0, null);
            g.dispose();
        } catch (MalformedURLException e) {
            System.out.println("URL格式异常" + e.getMessage());
        } catch (IOException e) {
            System.out.println("读取图片异常" + e.getMessage());
        }
        return resultImg;
    }



    /**
     * 自增序列号
     *
     * @param prefix    前缀
     * @param numLength 要生成多少位的数字
     * @return
     */
    public String SeqGenerator(String prefix, int numLength) {
        String upperCode = "";
        Long size = redisUtil.lGetListSize(prefix);//查找以prefix作为key值的数据长度
        if (size > 0) {//有数据
            //获取该key下面的所有值 （-1所有值；1下一个值）
            List<Object> values = redisUtil.lGet(prefix, 0, -1);
            upperCode = values.get(values.size() - 1).toString();//返回最后一个值
        }
        String returnCode = "";
        int Suffix;//后缀数字
        if (!oConvertUtils.isEmpty(upperCode)) {//有数据
            String sequence = upperCode.substring(prefix.length());//截取前缀开始的后面数字
            Suffix = Integer.parseInt(sequence);
            Suffix++;//最后的序号加一
        } else {//没有数据
            Suffix = 1;
        }
        returnCode = prefix + String.format("%0" + numLength + "d", Suffix);//后缀不够numLength长，前面补充0
        //存入Redis
        redisUtil.lSet(prefix,returnCode);
        return returnCode;
    }
}
